﻿using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using SuperRyoninRPG.Characters.Items;
using SuperRyoninRPG.Controller;
using SuperRyoninRPG.Display;
using SuperRyoninRPG.Main;

namespace SuperRyoninRPG.Characters
{
	public class Player : Character
	{
		private enum States
		{
			Super
		}

		private enum Actions
		{
			Celebrate
		}

		//無敵
		private float invincibleTime;
		private float maxInvincibleTime = 2.0f;
		public bool Invincible {
			get { return invincibleTime > 0; }
		}

		// 入力構成
		private const float MoveStickScale = 1.0f;
		private const float AccelerometerScale = 1.5f;
		private const Buttons JumpButton = Buttons.A;
		private const Buttons DushButton = Buttons.B;
		
		private const string FolderPath = "Images/Player/";

		/// <summary>
		///     新しいプレイヤーを構築します。
		/// </summary>
		public Player(Stage stage, Vector2 position)
			: base(stage, position,  FolderPath, 32)
		{
			this.MaxJumpTime = 0.75f;
		}

		protected override string[] GetStates()
		{
			return Enum.GetNames(typeof(States));
		}

		protected override string[] GetActions()
		{
			return Enum.GetNames(typeof (Actions));
		}

		/// <summary>
		///     プレイヤーの水平移動とジャンプ コマンドを入力から取得します。
		/// </summary>
		protected override void GetInput(
			GameTime gameTime,
			KeyboardState keyboardState,
			GamePadState gamePadState,
			TouchCollection touchState,
			AccelerometerState accelState,
			DisplayOrientation orientation)
		{
			this.Movement = gamePadState.ThumbSticks.Left.X * MoveStickScale;

			// 所定の位置での実行を妨げる小さな移動を無視します。
			if (Math.Abs(this.Movement) < 0.5f)
			{
				this.Movement = 0.0f;
			}

			// 加速度センサーの入力値を元にプレイヤーを移動させます
			if (Math.Abs(accelState.Acceleration.Y) > 0.10f)
			{
				// set our movement speed
				this.Movement = MathHelper.Clamp(-accelState.Acceleration.Y * AccelerometerScale, -1f, 1f);

				// if we're in the LandscapeLeft orientation, we must reverse our movement
				if (orientation == DisplayOrientation.LandscapeRight)
				{
					this.Movement = -this.Movement;
				}
			}
			// デジタル水平移動の入力が検出された場合、アナログ移動をオーバーライドします。
			if (gamePadState.IsButtonDown(Buttons.DPadLeft) ||
			    keyboardState.IsKeyDown(Keys.Left) ||
			    keyboardState.IsKeyDown(Keys.A))
			{
				this.Movement = -1.0f;
			}
			else if (gamePadState.IsButtonDown(Buttons.DPadRight) ||
			         keyboardState.IsKeyDown(Keys.Right) ||
			         keyboardState.IsKeyDown(Keys.D))
			{
				this.Movement = 1.0f;
			}

			if (this.IsOnGround)
			{
				if (this.Movement < 0)
				{
					this.Direction = FaceDirection.Left;
				}
				else if (this.Movement > 0)
				{
					this.Direction = FaceDirection.Right;
				}
			}

			// プレイヤーがジャンプするかどうかを
			// 確認します。
			this.IsJumping =
				gamePadState.IsButtonDown(JumpButton) ||
				keyboardState.IsKeyDown(Keys.Space) ||
				keyboardState.IsKeyDown(Keys.Up) ||
				keyboardState.IsKeyDown(Keys.X) ||
				touchState.AnyTouch();

			this.IsDushing = gamePadState.IsButtonDown(DushButton) ||
			                 keyboardState.IsKeyDown(Keys.Space) ||
			                 //keyboardState.IsKeyDown(Keys.Up) ||
			                 keyboardState.IsKeyDown(Keys.Z);

			this.IsCrouching = gamePadState.IsButtonDown(Buttons.DPadDown) || 
					keyboardState.IsKeyDown(Keys.Up);
		}

		protected override void OnMoved()
		{
			base.OnMoved();
			if (this.Position.X - this.FrameWidth / 2.0f < this.Stage.StagePosision)
			{
				this.Position = new Vector2(this.Stage.StagePosision + this.FrameWidth / 2.0f, this.Position.Y);
				this.Velocity = new Vector2(0, this.Velocity.Y);
			}
		}

		protected override TileCollision GetCollision(TileCollision collision, Rectangle bounds)
		{
			collision = base.GetCollision(collision, bounds);
			//if (bounds.Left < this.Stage.StagePosision)
			//{
			//    collision = TileCollision.Impassable;
			//}
			return collision;
		}

		protected override void OnUpdate(GameTime gameTime)
		{
			base.OnUpdate(gameTime);

			if (!Invincible)
			{
				return;
			}

			var elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
			invincibleTime -= elapsed;
			if (invincibleTime <= 0)
			{
				invincibleTime = 0;
				this.Switch = false;
			}
		}

		public override void OnDamaged(Character killedBy)
		{
			base.OnDamaged(killedBy);
			if (this.State ==States.Super.ToString() )
			{
				this.State = BaseState.Normal.ToString();
				this.invincibleTime = this.maxInvincibleTime;
				this.Switch = true;
			}
			else if(this.State == BaseState.Normal.ToString())
			{
				this.OnKilled(killedBy);
			}
		}

		public override void OnKilled(Character killedBy)
		{
			base.OnKilled(killedBy);

			this.IsJumping = true;
			this.ForceJump = true;
			DisableCollision = true;
			this.StopTime = 0.5f;
		}

		

		/// <summary>
		///     このプレイヤーがレベルの出口に到達したときに
		///     呼び出されます。
		/// </summary>
		public void OnReachedExit()
		{
			this.Action = Actions.Celebrate.ToString();
		}

		public void GetItem(Item item)
		{
			if (item is Mashroom)
			{
				this.State = States.Super.ToString();
			}
		}
	}
}